package org.dromara.authcode.service.impl;

import org.dromara.authcode.domain.*;
import org.dromara.authcode.domain.bo.AuthCodeBo;
import org.dromara.authcode.domain.bo.TDeviceBo;
import org.dromara.authcode.domain.bo.TDeviceOrderBo;
import org.dromara.authcode.domain.vo.TDeviceOrderVo;
import org.dromara.authcode.domain.vo.TGoodsVo;
import org.dromara.authcode.service.*;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.dromara.authcode.domain.bo.DeviceAuthBo;
import org.dromara.authcode.domain.vo.DeviceAuthVo;
import org.dromara.authcode.mapper.DeviceAuthMapper;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * 设备授权记录Service业务层处理
 *
 * @author Miles Meng
 * @date 2025-08-08
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DeviceAuthServiceImpl implements IDeviceAuthService {
    private final ITDeviceService tDeviceService;
    private final DeviceAuthMapper baseMapper;
    private final IAuthCodeService authCodeService;
    private final ITDeviceOrderService tDeviceOrderService;
    private final ITGoodsService tGoodsService;
    /**
     * 查询设备授权记录
     *
     * @param id 主键
     * @return 设备授权记录
     */
    @Override
    public DeviceAuthVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询设备授权记录列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 设备授权记录分页列表
     */
    @Override
    public TableDataInfo<DeviceAuthVo> queryPageList(DeviceAuthBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DeviceAuth> lqw = buildQueryWrapper(bo);
        Page<DeviceAuthVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询设备授权记录，根据设备ID查询最新的一条记录
     *
     * @param id 设备ID
     * @return 设备授权记录
     */
    public DeviceAuth getLastDeviceAuth(Long id) {
        return baseMapper.selectOne(
            new LambdaQueryWrapper<DeviceAuth>()
                .eq(DeviceAuth::getDeviceId, id.toString())
                .orderByDesc(DeviceAuth::getCreateTime)
                .last("limit 1"));
    }

    /**
     * 查询符合条件的设备授权记录列表
     *
     * @param bo 查询条件
     * @return 设备授权记录列表
     */
    @Override
    public List<DeviceAuthVo> queryList(DeviceAuthBo bo) {
        LambdaQueryWrapper<DeviceAuth> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DeviceAuth> buildQueryWrapper(DeviceAuthBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DeviceAuth> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(DeviceAuth::getId);
        lqw.eq(bo.getUserId() != null, DeviceAuth::getUserId, bo.getUserId());
        lqw.eq(bo.getDeviceId() != null, DeviceAuth::getDeviceId, bo.getDeviceId());
        lqw.eq(StringUtils.isNotBlank(bo.getAuthCode()), DeviceAuth::getAuthCode, bo.getAuthCode());
        lqw.eq(bo.getAuthCodeId() != null, DeviceAuth::getAuthCodeId, bo.getAuthCodeId());
        lqw.eq(bo.getAuthTime() != null, DeviceAuth::getAuthTime, bo.getAuthTime());
        lqw.eq(bo.getExpireTime() != null, DeviceAuth::getExpireTime, bo.getExpireTime());
        return lqw;
    }

    /**
     * 新增设备授权记录
     *
     * @param bo 设备授权记录
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(DeviceAuthBo bo) {
        DeviceAuth add = MapstructUtils.convert(bo, DeviceAuth.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改设备授权记录
     *
     * @param bo 设备授权记录
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(DeviceAuthBo bo) {
        DeviceAuth update = MapstructUtils.convert(bo, DeviceAuth.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceAuth entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除设备授权记录信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 激活设备
     *
     * @param bo  授权码/Mac 地址
     * @return 是否授权成功
     */
    @Transactional
    @Override
    public boolean activeDevice(DeviceAuthBo bo) {
        TDevice tDevice = tDeviceService.queryByMacAddress(bo.getMacAddress());
        if (tDevice == null) {
            log.info("设备不存在，创建一个设备，MAC地址: {}", bo.getMacAddress());
            return activeDeviceByQrCode(bo);
        }
        return activeFunction(bo, tDevice);
    }
    /**
     * 授权功能,添加授权记录，更新设备订单状态，更新授权码状态
     *
     * @param bo  授权码/Mac 地址
     * @return 是否授权成功
     */
    private boolean activeFunction(DeviceAuthBo bo, TDevice tDevice) {
        // 如果传入了授权码
        AuthCode authCode = authCodeService.queryByCode(bo.getAuthCode());
        // 授权码不存在
        if (authCode == null) {
            log.error("授权码不存在");
            return false;
        }
        // 授权码不是初始状态
        if (authCode.getStatus() != StatusCode.F.getStatusCode()) {
            log.error("授权码不是初始状态");
            return false;
        }

        AuthCodeBo upd = new AuthCodeBo();
        upd.setId(authCode.getId());
        upd.setStatus(StatusCode.T.getStatusCode()); // 已使用

        // 1、更新授权码状态
        boolean update = authCodeService.updateByBo(upd);
        if (!update) {
            log.error("更新授权码状态失败");
            return false;
        }

        // 获取商品信息
        TGoodsVo goods = tGoodsService.queryById(authCode.getGoodsId());

        // 添加设备授权记录
        DeviceAuthBo deviceAuthBo = new DeviceAuthBo();
        deviceAuthBo.setDeviceId(tDevice.getId()); // 设备ID,不使用mac地址
        deviceAuthBo.setAuthCode(bo.getAuthCode());
        deviceAuthBo.setAuthCodeId(authCode.getId());
        deviceAuthBo.setUserId(bo.getUserId());
        deviceAuthBo.setAuthTime(DateUtils.getNowDate()); // 授权时间

        // 到期时间,如果有多条数据，则取最晚的，然后计算剩余时间
        DeviceAuth deviceAuth = getLastDeviceAuth(tDevice.getId());
        if (deviceAuth != null) {
            // 如果授权过期时间在当前时间之前，则使用授权时间加授权时长
            if (deviceAuth.getExpireTime().before(DateUtils.getNowDate())) {
                deviceAuthBo.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusMonths(goods.getValidMonths())));
            } else {
                // 计算剩余时间
                long days = DateUtils.difference(DateUtils.getNowDate(), deviceAuth.getExpireTime(), TimeUnit.DAYS);
                // 加上剩余时间天数，再加上本次增加的月数
                if (days > 0 ) {
                    deviceAuthBo.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusDays(days).plusMonths(goods.getValidMonths())));
                } else {
                    deviceAuthBo.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusMonths(goods.getValidMonths())));
                }
            }

        } else {
            deviceAuthBo.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusMonths(goods.getValidMonths())));
        }
        // 2、添加设备授权记录
        this.insertByBo(deviceAuthBo);

        //3、添加或更新设备订单表
        // 查询设备订单表，如果存在则更新，不存在则添加 根据设备ID查询和商品ID查询
        TDeviceOrderBo tDeviceOrderBo = new TDeviceOrderBo();
        tDeviceOrderBo.setDeviceId(tDevice.getId());
        tDeviceOrderBo.setGoodsId(authCode.getGoodsId());

        List<TDeviceOrderVo> tDeviceOrderVos = tDeviceOrderService.queryList(tDeviceOrderBo);

        if (tDeviceOrderVos != null && !tDeviceOrderVos.isEmpty()) {
            TDeviceOrderVo tDeviceOrderVo = tDeviceOrderVos.getFirst();
            // 计算剩余时间
            long days = DateUtils.difference(DateUtils.getNowDate(), tDeviceOrderVo.getExpireTime(), TimeUnit.DAYS);
            // 加上剩余时间天数，再加上本次增加的月数
            if (days > 0 ) {
                tDeviceOrderVo.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusDays(days).plusMonths(goods.getValidMonths())));
            } else {
                tDeviceOrderVo.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusMonths(goods.getValidMonths())));
            }
            tDeviceOrderVo.setGoodsId(authCode.getGoodsId());

            TDeviceOrderBo tDeviceOrderUpdateBo =  MapstructUtils.convert(tDeviceOrderVo, TDeviceOrderBo.class);
            // 更新设备订单表
            tDeviceOrderService.updateByBo(tDeviceOrderUpdateBo);
        } else {
            // 新增设备订单表
            TDeviceOrderBo add = new TDeviceOrderBo();
            add.setDeviceId(tDevice.getId());
            add.setGoodsId(authCode.getGoodsId());
            add.setExpireTime(DateUtils.toDate(LocalDateTime.now().plusMonths(goods.getValidMonths())));
            tDeviceOrderService.insertByBo(add);
        }

        return true;
    }

    /**
     * 授权功能
     *
     * @param bo  授权码/Mac 地址
     * @return 是否授权成功
     */
    @Override
    public boolean checkFunction(DeviceAuthBo bo) {
        //bo对象属性为Mac地址
        TDevice tDevice = tDeviceService.queryByMacAddress(bo.getMacAddress());
        // 设备不存在，为空，则返回false
        if (tDevice == null) {
            log.error("设备不存在，MAC地址: {}", bo.getMacAddress());
            return false;
        }
        // TODO 后续考虑新用户免费使用*天

        TDeviceOrderBo tDeviceOrderBo = new TDeviceOrderBo();
        tDeviceOrderBo.setDeviceId(tDevice.getId());
        tDeviceOrderBo.setGoodsId(bo.getGoodsId()); // 商品ID,参数传入
        List<TDeviceOrderVo> tDeviceOrderVos = tDeviceOrderService.queryList(tDeviceOrderBo);

        if (tDeviceOrderVos != null && !tDeviceOrderVos.isEmpty()) {
            TDeviceOrderVo tDeviceOrderVo = tDeviceOrderVos.getFirst();
            Date expires = tDeviceOrderVo.getExpireTime();
            // 过期时间在当前时间之后，Assert.isTrue表达式为true不抛异常，否则抛异常:授权码已过期
            if (expires == null) {
                log.error("授权码已过期");
                return false;
            } else {
                return expires.after(DateUtils.getNowDate());
            }
        } else {
            return false;
        }
    }

    /**
     * 激活功能(二维码激活)
     * mac地址不存在则添加
     * @param bo  授权码/Mac 地址
     * @return 是否授权成功
     */
    @Override
    @Transactional
    public boolean activeDeviceByQrCode(DeviceAuthBo bo) {
        //bo对象属性为Mac地址
        TDevice tDevice = tDeviceService.queryByMacAddress(bo.getMacAddress());
        // 设备不存在，为空，则返回false
        if (tDevice == null) {
            TDeviceBo deviceBo = new TDeviceBo();
            deviceBo.setMacAddress(bo.getMacAddress());
            deviceBo.setAlias("Bluetooth Device");
            deviceBo.setAppVersion("1.0.0");
            deviceBo.setBoard("Bluetooth");
            deviceBo.setUserId(1L);
            deviceBo.setActiveStatus(1L);
            if (tDeviceService.insertByBo(deviceBo)) {
                tDevice = tDeviceService.queryByMacAddress(bo.getMacAddress());
            } else {
                log.error("设备添加失败，MAC地址: {}", bo.getMacAddress());
                return false;
            }
        }
        return activeFunction(bo, tDevice);
    }

}
